package com.bgds.sys.api.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bgds.sys.api.bean.mars.bo.DtUserBo;
import com.bgds.sys.api.bean.mars.dto.*;
import com.bgds.sys.api.bean.mars.vo.WaveDataVO;
import com.bgds.sys.api.constant.MarsConstant;
import com.bgds.sys.api.feign.MarsFeignClient;
import com.bgds.sys.api.service.DeTongService;
import com.bgds.sys.common.constant.BizConstant;
import com.bgds.sys.common.exception.BusinessException;
import com.bgds.sys.module.entity.Region;
import com.bgds.sys.module.service.IDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: warm
 * @Description:
 * @Date: 2020/7/27 15:22
 * @Version: 1.0
 */
@Service
@Slf4j
public class DeTongServiceImpl implements DeTongService {

    @Autowired
    private MarsFeignClient marsFeignClient;

    @Resource
    IDeviceService iDeviceService;

    @Value("${detong.username}")
    private String username;
    @Value("${detong.password}")
    private String password;


    @Override
    public Map<String, String> getToken() {
        DtUserBo dtUserBo = new DtUserBo(username, password);
        Map<String, String> map = marsFeignClient.auth(dtUserBo);
        return map;
    }

    @Override
    public List<TreeDto> tree() {
        //获取用户token
        String token = checkToken();
        List<TreeDto> treeDtos = marsFeignClient.tree(token);
        return treeDtos;
    }

    @Override
    public NodeDto listNodeById(String id) {
        //获取用户token
        String token = checkToken();
        NodeDto nodes = marsFeignClient.listNode(id, token);
        return nodes;
    }

    /**
     * 历史数据
     *
     * @param id
     * @param code
     * @param startTime
     * @param endTime
     * @param pageIndex
     * @param pageSize
     * @return
     * @throws ParseException
     */
    @Override
    public HistoryDataVo getHisData(String id, Integer code, String startTime, String endTime, Integer pageIndex, Integer pageSize) {
        HistoryDataVo result = new HistoryDataVo();
        //获取用户token
        String token = checkToken();
        List<TrendDataDto> hisDatas = new ArrayList<>();
        Integer total = getHisCount(id, code, startTime, endTime);
        if (total == 0) {
            total = 1;
            result.setTotal(0);
        } else {
            result.setTotal(total);
        }
        //若趋势数据，没有发送pageIndex和pageSize，全量返回数据

        if (null != pageIndex && 0 != pageIndex && null != pageSize && 0 != pageSize) {
            //调用厂家接口请求历史数据
            hisDatas = marsFeignClient.getHisData(id, code, startTime, endTime, pageIndex, pageSize, token);
        } else {
            hisDatas = marsFeignClient.getHisData(id, code, startTime, endTime, 1, total, token);
        }

        result.setHisDataList(hisDatas);

        return result;
    }

    /**
     * 历史数据量
     *
     * @param id
     * @param code
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public Integer getHisCount(String id, Integer code, String startTime, String endTime) {
        //获取用户token
        String token = checkToken();
        //调用厂家接口获取节点指标数据量
        Integer hisCount = marsFeignClient.getHisCount(id, code, startTime, endTime, token);
        return hisCount;
    }

    /**
     * 查询波形数据
     *
     * @param id
     * @param code
     * @param time
     * @param type
     * @return
     */

    @Override
    public List<WaveDataVO> getWaveData(String id, Integer code, String time, Integer type) {

        List<WaveDataVO> resultDatas = new ArrayList<>();
        //获取用户token
        String token = checkToken();
        //获取测点的数据
        WaveDataDto waveData = new WaveDataDto();
        switch (type) {
            case 1:
                //时域波形
                waveData = marsFeignClient.getWaveData(id, code, time, token);
                break;
            case 2:
                //查询倒谱数据
                waveData = marsFeignClient.getCepstrumData(id, code, time, token);
                break;
            default:
        }
        //处理数据
        resultDatas = processData(waveData);
        return resultDatas;
    }

    @Override
    public void getWaveData(String id, Integer code, String time, Integer type, HttpServletResponse response) {
        //获取用户token
        String token = checkToken();
        //获取测点的数据
        byte[] json = new byte[]{};
        switch (type) {
            case 1:
                //时域波形
                json = marsFeignClient.getWaveData(id, code, time, token, "application/x-msgpack;charset=UTF-8", "gzip, deflate", "zh-CHS");
                break;
            case 2:
                //查询倒谱数据
                json = marsFeignClient.getCepstrumData(id, code, time, token, "application/x-msgpack;charset=UTF-8", "gzip, deflate", "zh-CHS");
                break;
            default:

        }
        response.setCharacterEncoding("UTF-8");
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void getSpectrumData(String id, Integer code, String time, HttpServletResponse response) {
        //获取用户token
        String token = checkToken();
        byte[] json = marsFeignClient.getSpectrumData(id, code, time, token, "application/x-msgpack;charset=UTF-8", "gzip, deflate", "zh-CHS");
        response.setCharacterEncoding("UTF-8");
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 包络数据
     *
     * @param id
     * @param code
     * @param time
     * @param centerFreq
     * @param filterWidth
     * @return
     */
    @Override
    public List<WaveDataVO> getEnvelopeData(String id, Integer code, String time, Double centerFreq, Double filterWidth) {

        List<WaveDataVO> resultDatas = new ArrayList<>();
        //获取用户token
        String token = checkToken();

        //获取对应的测点id

        String thirdPointId = "";

        WaveDataDto envelopeData = marsFeignClient.getEnvelopeData(id, code, time, centerFreq, filterWidth, token);

        resultDatas = processData(envelopeData);
        return resultDatas;
    }

    @Override
    public void getEnvelopeData(String id, Integer code, String time, Double centerFreq, Double filterWidth, HttpServletResponse response) {

        List<WaveDataVO> resultDatas = new ArrayList<>();
        //获取用户token
        String token = checkToken();

        //获取对应的测点id

        String thirdPointId = "";

        byte[] json = marsFeignClient.getEnvelopeData(id, code, time, centerFreq, filterWidth, token, "application/x-msgpack;charset=UTF-8", "gzip, deflate", "zh-CHS");
        response.setCharacterEncoding("UTF-8");
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public IPage<AlarmEventDto> pageAlarmEventDto(Integer detailCount, Integer pageIndex, Integer pageSize) {
        //获取用户token
        String token = checkToken();
        List<AlarmEventDto> alarmEventDtos = marsFeignClient.getAlarm(detailCount, pageIndex, pageSize, token);
        Integer count = marsFeignClient.getAlarmCount(token);
        IPage<AlarmEventDto> page = new Page<AlarmEventDto>().setCurrent(pageIndex).setTotal(count).setPages(pageSize).setRecords(alarmEventDtos);
        return page;
    }

    @Override
    public List<DataTimeSerise> getLastVibData(String id) {
        //获取用户token
        String token = checkToken();
        List<DataTimeSerise> dataTimeSerises = marsFeignClient.getLastData(id, 101, token);
        return dataTimeSerises;
    }

    @Override
    public List<DataTimeSerise> getLastTempData(String id) {
        //获取用户token
        String token = checkToken();
        List<DataTimeSerise> dataTimeSerises = marsFeignClient.getLastData(id, 100, token);
        return dataTimeSerises;
    }

    @Override
    public List<AlarmDeviceDto> pageAlarmByDeviceId(String relationId, Integer detailCount, String startTime, String endTime) {
        LocalDateTime start = DateUtil.parseLocalDateTime(startTime);
        LocalDateTime end = DateUtil.parseLocalDateTime(endTime);
        //获取用户token
//            String token = checkToken();
//        List<AlarmEventDto> alarmEventDtos = marsFeignClient.getAlarm(detailCount, pageIndexAll, pageSizeAll, token);
        //todo  Mock数据
        String s = HttpUtil.get("https://mock.apipost.cn/app/mock/project/5562d5f4-9825-4b63-a8b4-499a6f32a243/deviceAlarm");
        List<AlarmEventDto> alarmEventDtos = JSON.parseArray(s, AlarmEventDto.class);
        if (CollectionUtil.isEmpty(alarmEventDtos)) {
            return Collections.emptyList();
        }
        log.info("总报警数：{}", alarmEventDtos.size());

        //根据设备id进行过滤
        List<AlarmEventDto> deviceAlarmTotalList = alarmEventDtos.stream()
                .filter(alarm -> relationId.equalsIgnoreCase(alarm.getEventNodeId())).collect(Collectors.toList());
        log.info("{}设备总报警数：{}", relationId, deviceAlarmTotalList.size());
        if (CollectionUtil.isEmpty(deviceAlarmTotalList)) {
            log.info("{}该设备不存在报警数据", relationId);
            return Collections.emptyList();
        }

        List<AlarmDeviceDto> records = new ArrayList<>();
        deviceAlarmTotalList.forEach(r -> {
            String relationId2 = r.getEventNodeId();
            String deviceName = r.getEventNodeName();
            Region region = iDeviceService.getRegionByRelationId(relationId2);
            List<AlarmEventDetails> detailsList = r.getDetails();
            detailsList.forEach(detail -> {
                //进行时间过滤
                LocalDateTime alarmTime = DateUtil.toLocalDateTime(detail.getEdTime());
                if (!(alarmTime.isAfter(start)&&alarmTime.isBefore(end))){
                    return;
                }
                AlarmDeviceDto alarmDeviceDto = new AlarmDeviceDto();
                alarmDeviceDto.setRelationId(relationId2);
                alarmDeviceDto.setAlarmPointRelationId(detail.getEdNodeId());
                alarmDeviceDto.setDeviceName(deviceName);
                alarmDeviceDto.setAlarmPoint(detail.getNodeName());
                alarmDeviceDto.setRegionName(region.getName());
                alarmDeviceDto.setAlarmTime( alarmTime);
                alarmDeviceDto.setAlarmInfo(BizConstant.ALARM_INFO);
                records.add(alarmDeviceDto);
            });
        });

        return records;
    }

    /**
     * 获取 任意值
     *
     * @param id
     * @return
     */
    @Override
    public List<DataTimeSerise> getObject(String id, Integer code) {
        //获取用户token
        String token = null;
        List<DataTimeSerise> dataTimeSerises = null;
        try {
            token = checkToken();
            dataTimeSerises = marsFeignClient.getLastData(id, code, token);
        } catch (Exception e) {
            return null;
        }
        return dataTimeSerises;
    }

    private String checkToken() {
        Map<String, String> result = getToken();
        if (Objects.isNull(result) || !result.containsKey(MarsConstant.TOKEN)) {
            throw new BusinessException(401, "德通认证用户失败");
        }
        String token = result.get(MarsConstant.TOKEN);
        token = MarsConstant.TOKEN_SPLIT + token;

        return token;
    }


    private List<WaveDataVO> processData(WaveDataDto dataDto) {
        List<WaveDataVO> result = new ArrayList<>();
        List<Float> dataResult = dataDto.getData();
        Float xInterval = dataDto.getXInterval();
        for (int i = 0; i < dataResult.size(); i++) {
            if (null != dataResult.get(i) && 0 != dataResult.get(i)) {
                WaveDataVO resultData = new WaveDataVO();
                resultData.setInterval(i * xInterval);
                resultData.setValue(dataResult.get(i));

                result.add(resultData);
            }
        }
        return result;
    }
}